package nodes.command;

import java.util.*;
import reflection.Reflection;
import model.Model;
import nodes.AbstractNode;


/**
 * A command node (used for commands such as pendown)
 * 
 * @author Andrew Patterson
 */
public class CommandNode extends AbstractNode
{
    private static final String COMMAND_TO_CLASSES_FILE = "resources.commandLabelsToClasses";
    private static Map<String, AbstractCommand> SUPPORTED_COMMANDS;
    private List<AbstractNode> myArguments;


    public CommandNode (String name, Model model)
    {
        super(model);
        myName = name;
        myArguments = new ArrayList<AbstractNode>();
    }
    
    /**
     * A static constructor which calls loadCommands(...) at some point before this class is used
     */
    static
    {
        loadCommands(COMMAND_TO_CLASSES_FILE);
    }
    
    @Override
    public AbstractNode buildTree(Queue<AbstractNode> stack)
    {
        myArguments = SUPPORTED_COMMANDS.get(myName).setUpCommand(stack,myName);
        return this;
    }


    /**
     * Uses reflection to map function strings to the class that represents them
     */
    public static void loadCommands (String commandPackage)
    {
        SUPPORTED_COMMANDS = new HashMap<String, AbstractCommand>();
        ResourceBundle myResources = ResourceBundle.getBundle(commandPackage);
        for (String key : myResources.keySet())
        {
            SUPPORTED_COMMANDS.put(key, (AbstractCommand) Reflection.createInstance(myResources.getString(key)));
        }
    }


    @Override
    public String toString ()
    {
        if (myArguments != null) return myName + myArguments.toString();
        else return myName;
    }


    public AbstractNode evaluate ()
    {
        return SUPPORTED_COMMANDS.get(myName).evaluate(myArguments,myModel);
    }
}
